package com.commons.dbutils.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.qunar.constant.HttpStatusCodeConstant;
import com.qunar.service.hotel.ota.domain.request.BaseRequest;
import com.qunar.utils.DateUtil;
import com.qunar.utils.HttpRequestResultUtil;
import com.qunar.utils.MailUtil;


public class HotelCpcAsyncHttpClientUtil {
	private static final Logger log = Logger.getLogger(HotelCpcAsyncHttpClientUtil.class);
	
	private static final Counter counter = new Counter();
	private static final String GET_METHOD  = "getContext";
	private static final String POST_METHOD ="hotelCpcAsyncPostRequest";

	private static  void errorEmailLogManager(String methodName,Exception ex,String repStr
											,BaseRequest baseRequest,String code){
		Object[] objs = null;
		boolean needSendEmail = !baseRequest.isNeedCount();
		StringBuffer buffer=null;
		if(baseRequest.isNeedCount()){
			
			StringBuffer keyBuffer = new StringBuffer(StringUtils.trimToEmpty(code));
			keyBuffer.append(StringUtils.trimToEmpty(baseRequest.getCountKey()));
			keyBuffer.append(baseRequest.getOtaName());
			
			String key = keyBuffer.toString();
			synchronized(counter){
				
				counter.add(key);
				if(counter.isMaxNumber(key)){
					objs = counter.clearByKey(key);
					int num = objs[0]!=null?(Integer)objs[0]:0;
					long addTime = objs[1]!=null?(Long)objs[1]:0;
					if(addTime>0 && num>0){
						needSendEmail = true;
						buffer = new StringBuffer();
						buffer.append(baseRequest.getOtaName());
						buffer.append("-在(内网)ip为：");
						buffer.append(HotelCpcTools.getEth0Address());
						buffer.append("的服务上,");
						buffer.append("在 ");
						buffer.append(DateUtil.formatDate(new Date(addTime), DateUtil.FORMAT_ALL_M));
						buffer.append(" 至 ");
						buffer.append(DateUtil.formatDate(DateUtil.getCurrentTime(), DateUtil.FORMAT_ALL_M));
						buffer.append(" 共发生了");
						buffer.append(num);
						buffer.append("次异常，异常说明如下：<br/>");
						
					}
					
				}
			}
			
		}
		
		if(needSendEmail){
			if(buffer==null){
				buffer = new StringBuffer();
			}
			buffer.append(MobilePPBOTAUtils.LOG_EXP);
			buffer.append(StringUtils.trimToEmpty(baseRequest.getOtaName()));
			buffer.append("(");
			buffer.append(HotelCpcTools.getEth0Address());
			buffer.append(")-");
			
			buffer.append(StringUtils.trimToEmpty(HotelCpcAsyncHttpClientUtil.class.getSimpleName()));
			buffer.append(".");
			buffer.append(StringUtils.trimToEmpty(methodName));
			
			if(ex!=null){
				buffer.append(" <br/>");
				buffer.append(ex.toString());
			}else{
				buffer.append(" no error request result is null");
			}
			
			buffer.append(",<br/>url:");
			buffer.append(StringUtils.trimToEmpty(baseRequest.getUrl()));
			buffer.append(",<br/>requestContent is ");
			buffer.append(StringUtils.defaultIfBlank(baseRequest.getRequestParamEmailLog(), "null"));
			buffer.append(",<br/>responseContent is ");
			buffer.append(StringUtils.defaultIfBlank(repStr, "null"));
			
			MailUtil.emailAlarm(new StringBuffer(MobilePPBOTAUtils.EMAIL_TITLE_EXP).append(baseRequest.getOtaName()).append("(红色)").toString(), buffer.toString(), MailUtil.MOBILE_PPB_EMAIL_ALERT);
		}
		
		return ;
	}
	public static void errorLogManager(String methodName,Exception ex,String repStr,BaseRequest baseRequest){
		StringBuffer buffer = new StringBuffer(MobilePPBOTAUtils.LOG_EXP);
		buffer.append(StringUtils.trimToEmpty(baseRequest.getOtaName()));
		buffer.append(" ");
		buffer.append(StringUtils.trimToEmpty(HotelCpcAsyncHttpClientUtil.class.getSimpleName()));
		buffer.append(".");
		buffer.append(StringUtils.trimToEmpty(methodName));
		
		if(ex!=null){
			buffer.append(" ");
			buffer.append(ex.toString());
		}else{
			buffer.append(" no error request result is null");
		}
		
		buffer.append(",url:");
		buffer.append(StringUtils.trimToEmpty(baseRequest.getUrl()));
		buffer.append(",requestContent is ");
		buffer.append(StringUtils.defaultIfBlank(HotelCpcTools.replaceBlank(baseRequest.getRequestParamLog()), "null"));
		buffer.append(",responseContent is ");
		buffer.append(StringUtils.defaultIfBlank(repStr, "null"));
		
		log.error(buffer.toString());
	}
	public static String getContext(BaseRequest baseRequest,int connTimeout, int readTimeout) {
		return getContext(baseRequest, null,connTimeout,readTimeout);
	}
	
	public static String getContext(BaseRequest baseRequest, Map<String,String> cookies,int connTimeout, int readTimeout){
		
		String ret = null;
		int httpStatusCode = 0;
		DefaultHttpClient client = new DefaultHttpClient(); 
		HttpParams pms = client.getParams();
		HttpConnectionParams.setConnectionTimeout(pms, connTimeout);
		HttpConnectionParams.setSoTimeout(pms, readTimeout);
		HttpGet getMethod = new HttpGet(baseRequest.getUrl());
		HttpResponse httpresponse=null;
		StatusLine sl=null;
		//添加cookie请求
		if(cookies != null && cookies.size() > 0) {
			CookieStore cookieStores = client.getCookieStore();   
			BasicClientCookie cookie=null;
			for(String key:cookies.keySet()) {
				cookie = new BasicClientCookie(key, cookies.get(key));
				cookieStores.addCookie(cookie);
			}
			client.setCookieStore(cookieStores);
			
		}
	
		long startTime = System.currentTimeMillis();
		
		try {
			httpresponse = client.execute(getMethod);
			// 获取返回数据
			sl = httpresponse.getStatusLine();
			if(sl != null){
				httpStatusCode = sl.getStatusCode();
				if(httpStatusCode==200){
					ret=EntityUtils.toString(httpresponse.getEntity());  
				}else{
					log.info(new StringBuffer("Get ").append(StringUtils.trimToEmpty(baseRequest.getUrl())).append(" http error:").append(httpStatusCode));
				}
			}else{
				httpStatusCode = HttpStatusCodeConstant.NULL_EXCEPTION;
				errorLogManager(GET_METHOD,null,ret,baseRequest);
				errorEmailLogManager(GET_METHOD,null,ret,baseRequest,String.valueOf(httpStatusCode));
				
			}
			
			
		}catch (UnsupportedEncodingException e) {
			httpStatusCode = HttpStatusCodeConstant.UNSUPPORTEDENCODING_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,null);
		
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			httpStatusCode = HttpStatusCodeConstant.CLIENTPROTOCOL_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
		
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,null);
			e.printStackTrace();
		} catch (ParseException e) {
			httpStatusCode = HttpStatusCodeConstant.PARSE_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			
			
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,null);
			e.printStackTrace();
		}catch(ConnectTimeoutException e){
			httpStatusCode = HttpStatusCodeConstant.CONNECT_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,String.valueOf(httpStatusCode));
			e.printStackTrace();
		}catch(SocketTimeoutException e){
			httpStatusCode = HttpStatusCodeConstant.SOCKET_TIMEOUT_EXCEPTION;
			//错误日志记录
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			//邮件报警
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,String.valueOf(httpStatusCode));
			//增加短信告警统计
			CountUtils.timeOutCount(baseRequest.getOtaName(), baseRequest.getUrl());
			e.printStackTrace();
		}catch (IOException e) {
			httpStatusCode = HttpStatusCodeConstant.IO_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,null);
			e.printStackTrace();
		}catch(Exception e) {
			httpStatusCode = HttpStatusCodeConstant.OTHER_EXCEPTION;
			errorLogManager(GET_METHOD,e,ret,baseRequest);
			
			errorEmailLogManager(GET_METHOD,e,ret,baseRequest,null);
			e.printStackTrace();
		}finally {
			if (getMethod != null) {
				getMethod.abort();
			}
			if (client != null) {
				client.getConnectionManager().shutdown();
			}
		}
		HttpRequestResultUtil.monitor(baseRequest.getUrl(), System.currentTimeMillis() - startTime, httpStatusCode, ret);
		return ret;
	}

	
	
	/**
	 * 异步post请求
	 * @param postContent 请求的内容
	 * @param url 请求的url
	 * @param connTimeout 连接超时时间
	 * @param reqTime 请求超时时间
	 * @return
	 */
	public static String hotelCpcPostRequest(BaseRequest postContent, int connTimeout, int reqTimeout, Map<String,String> cookies) {
		
		String ret = null;
		int httpStatusCode = 0;
		DefaultHttpClient client = new DefaultHttpClient(); 
		HttpParams pms = client.getParams();
		HttpConnectionParams.setConnectionTimeout(pms, connTimeout);
		HttpConnectionParams.setSoTimeout(pms, reqTimeout);
		HttpPost postMethod = new HttpPost(postContent.getUrl());
		HttpResponse httpresponse=null;
		StatusLine sl=null;
		//添加cookie请求
		if(cookies != null && cookies.size() > 0) {
			CookieStore cookieStores = client.getCookieStore();   
			BasicClientCookie cookie=null;
			for(String key:cookies.keySet()) {
				cookie = new BasicClientCookie(key, cookies.get(key));
				cookieStores.addCookie(cookie);
			}
			client.setCookieStore(cookieStores);
			
		}
		HttpEntity httpEntity = null;
		long startTime = System.currentTimeMillis();
		
		try {
			if(StringUtils.isNotBlank(postContent.getRequestBody())) {
				httpEntity= new StringEntity(postContent.getRequestBody(),HTTP.UTF_8);
			}else if(postContent.getRequestParameters()!=null && postContent.getRequestParameters().size()>0){
				List<NameValuePair> paramList = new ArrayList<NameValuePair>(postContent.getRequestParameters().size()); 
				for(String key:postContent.getRequestParameters().keySet()){
					paramList.add(new BasicNameValuePair(key, postContent.getRequestParameters().get(key)));
				}
				httpEntity = new UrlEncodedFormEntity(paramList, HTTP.UTF_8);
			}else{
				httpEntity= new StringEntity(StringUtils.EMPTY,HTTP.UTF_8);
			}
			
				
			postMethod.setEntity(httpEntity);
			httpresponse = client.execute(postMethod);
			httpEntity.consumeContent();
			// 获取返回数据
			sl = httpresponse.getStatusLine();
		
			if(sl != null){
				httpStatusCode = sl.getStatusCode();
				if(httpStatusCode==200){
					ret=EntityUtils.toString(httpresponse.getEntity());  
				}else{
					log.info(new StringBuffer("Get ").append(StringUtils.trimToEmpty(postContent.getUrl())).append(" http error:").append(httpStatusCode));
				}
			}else{
				httpStatusCode = HttpStatusCodeConstant.NULL_EXCEPTION;
				errorLogManager(POST_METHOD,null,ret,postContent);
				
				errorEmailLogManager(POST_METHOD,null,ret,postContent,String.valueOf(httpStatusCode));
				
				
			}
		} catch (UnsupportedEncodingException e) {
			httpStatusCode = HttpStatusCodeConstant.UNSUPPORTEDENCODING_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			errorEmailLogManager(POST_METHOD,e,ret,postContent,null);
			
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			
			httpStatusCode = HttpStatusCodeConstant.CLIENTPROTOCOL_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			errorEmailLogManager(POST_METHOD,e,ret,postContent,null);
			e.printStackTrace();
		} catch (ParseException e) {
			httpStatusCode = HttpStatusCodeConstant.PARSE_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			errorEmailLogManager(POST_METHOD,e,ret,postContent,null);
			e.printStackTrace();
		}catch(ConnectTimeoutException e){
			httpStatusCode = HttpStatusCodeConstant.CONNECT_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			
			errorEmailLogManager(POST_METHOD,e,ret,postContent,String.valueOf(httpStatusCode));
			
			e.printStackTrace();
		}catch(SocketTimeoutException e){
			httpStatusCode = HttpStatusCodeConstant.SOCKET_TIMEOUT_EXCEPTION;
			
			errorLogManager(POST_METHOD,e,ret,postContent);
			
			errorEmailLogManager(POST_METHOD,e,ret,postContent,String.valueOf(httpStatusCode));
			//增加短信告警统计
			CountUtils.timeOutCount(postContent.getOtaName(), postContent.getUrl());
			e.printStackTrace();
		}catch (IOException e) {
			httpStatusCode = HttpStatusCodeConstant.IO_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			
			errorEmailLogManager(POST_METHOD,e,ret,postContent,null);
			
			e.printStackTrace();
		}catch(Exception e) {
			httpStatusCode = HttpStatusCodeConstant.OTHER_EXCEPTION;
			errorLogManager(POST_METHOD,e,ret,postContent);
			
			errorEmailLogManager(POST_METHOD,e,ret,postContent,null);
			e.printStackTrace();
		}finally {
			if (postMethod != null) {
				postMethod.abort();
			}
			if (client != null) {
				client.getConnectionManager().shutdown();
			}
		}
		HttpRequestResultUtil.monitor(new StringBuffer(StringUtils.trimToEmpty(postContent.getUrl())).append("?").append(HotelCpcTools.replaceBlank(postContent.getRequestParamLog())).toString(), System.currentTimeMillis() - startTime, httpStatusCode, ret);
		return ret;
	}
	
	
	public static String hotelCpcAsyncPostRequest(BaseRequest postContent,  int connTimeout, int reqTimeout) {

		return hotelCpcPostRequest(postContent, connTimeout, reqTimeout, null);
	}
	
}
